package main

import (
	"encoding/json"
	"fmt"
	"net"

	"github.com/pan2za/qos-client/binapi/classify"
	"github.com/pan2za/qos-client/binapi/policer"
)

//for table
// for session
//for policer
//`{"is_add":true,"name":"policer2","cir":888,"cb":9999,"rate_type":0,"round_type":0,"type":0,"conform_action":1, "exceed_action":0}`
//Cir           uint32
//Eir           uint32
//Cb            uint64
//Eb            uint64
//RateType      uint8
//RoundType     uint8
//PolicerType          uint8
///ColorAware    bool
//ConformAction uint16
//ExceedAction  uint16
//ViolateAction uint16

// for apply
type QosConfig struct {
	Type               string                               `binapi:"string[64],name=type" json:"type,omitempty"`
	IsAdd              bool                                 `binapi:"bool,name=is_add" json:"is_add,omitempty"`
	Mask               string                               `binapi:"string[8],name=mask" json:"mask,omitempty"`
	ClassifyTableIndex uint32                               `binapi:"u32,name=classify_table_index" json:"classify_table_index,omitempty"`
	PolicerName        string                               `binapi:"string[64],name=policer_name" json:"policer_name,omitempty"`
	PolicerRule        policer.PolicerAddDel                `binapi:"PolicerAddDel,name=policer_rule" json:"policer_rule,omitempty"`
	ClassifySession    classify.ClassifyAddDelSession       `binapi:"ClassifyAddDelSession,name=classify_session" json:"classify_session,omitempty"`
	SetInterface       classify.PolicerClassifySetInterface `binapi:"PolicerClassifySetInterface,name=set_interface" json:"set_interface,omitempty"`
	SwIfName           string                               `binapi:"string[64],name=sw_if_name" json:"sw_if_name,omitempty"`
	StartTime          string                               `binapi:"string[8],name=start_time" json:"start_time,omitempty"`
	EndTime            string                               `binapi:"string[8],name=end_time" json:"end_time,omitempty"`
}

func doServerStuff(conn net.Conn) {
	remote := conn.RemoteAddr().String()
	fmt.Println(remote, " connected!")
	for {
		buf := make([]byte, 2048)
		size, err := conn.Read(buf)
		if err != nil {
			fmt.Println("Read Error:", err.Error())
			return
		}
		fmt.Println("data from client:", string(buf), "size:", size)
		var qos_config QosConfig
		// test :=
		// 	`{
		// 		"type":"/vpp/policer",
		// 		"is_add":true,
		// 		"policer_name":"policy1",
		// 		"policer_rule":[
		// 			{
		// 				"is_add":true,
		// 				"name":"policy1",
		// 				"cir":888,
		// 				"cb":9999,
		// 				"rate_type":0,
		// 				"round_type":0,
		// 				"type":0
		// 			}
		// 		]
		// }`

		// testmatch := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		// 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		// 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		// 	0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00}
		// jsonmatch, _ := json.Marshal(testmatch)
		// fmt.Println(jsonmatch)

		err = json.Unmarshal(buf[:size], &qos_config)
		//err = json.Unmarshal([]byte(test), &qos_config)
		if err != nil {
			fmt.Println("Unmarshal Error:", err.Error())
			return
		}
		fmt.Printf("%+v\n", qos_config)
		fmt.Println("QosConfig after Unmarshal:", qos_config)
		result := jclient_connect_vpp(&qos_config)

		buf, err = json.Marshal(result)
		if err != nil {
			fmt.Println("Marshal Error:", err.Error())
			return
		}
		//reply to java
		conn.Write(buf)
		conn.Close()
		break
	}
}
func main() {
	fmt.Println("Starting the server...")
	listener, err := net.Listen("tcp", "0.0.0.0:50000")
	if err != nil {
		fmt.Println("Listen Error:", err.Error())
		return
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Accept Error:", err.Error())
			return
		}
		go doServerStuff(conn)
	}
}
